05 - zweifaktorielle between ANOVA

Auswertung Emprischer Daten

Prof. Dr. David F. Urschler

Vorgehensweise

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktorielle ANOVA) --> 
G(Ergebnis berichten)

Beispiel

Erzielen Hunde oder Katzen mehr Likes, wenn sie auf unterschiedlichen
Social-Media-Plattformen präsentiert werden?

Information zum Datensatz

ae_anova_two_way_bet.csv

  • demographische Daten (id, age & gen: 0 = weiblich, 1 = männlich)
  • Tier (ani: 0 = Hund, 1 = Katze)
  • Social-Media-Plattform (0 = Instagramm, 2 = TikTok)
  • Absolute Anzahl der Likes (likes)

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktoriell ANOVA) --> 
G(Ergebnis berichten)

style A fill: #009e73

Daten einlesen

Zeig mir den Code
ds <- read.csv(here::here("ae_anova_two_way_bet.csv"),
               header = TRUE)

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktoriell ANOVA) --> 
G(Ergebnis berichten)

style B fill: #009e73

Übersicht verschaffen



id age gen ani smp likes
1 29 0 0 1 83
2 19 1 0 0 123
3 27 1 0 0 129
4 18 0 1 1 127
5 26 0 1 0 84
6 19 0 0 0 130

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktoriell ANOVA) --> 
G(Ergebnis berichten)

style C fill: #009e73

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktoriell ANOVA) --> 
G(Ergebnis berichten)

style D fill: #009e73

Ergeben die Daten Sinn?

UVs

Zeig mir den Code
# Tier
table(ds$ani)

# Social-Media-Plattform
table(ds$smp)

Ergeben die Daten Sinn?

demographische Daten

Zeig mir den Code
# Gender
table(ds$gen)

# Social-Media-Plattform
summary(ds$age)

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktoriell ANOVA) --> 
G(Ergebnis berichten)

style E fill: #009e73

Skalenwerte berechnen

UVs als Faktor

Zeig mir den Code
# Tier
ds$ani_f <- factor(ds$ani,
                   levels = c(0, 1),
                   labels = c("Hund", "Katze"))

# Social-Media-Plattform
ds$smp_f <- factor(ds$smp,
                   levels = c(0, 1),
                   labels = c("Instagramm", "TikTok"))

Skalenwerte berechnen

Demographische Variablen als Faktor

Zeig mir den Code
# Gender
ds$gen_f <- factor(ds$gen,
                   levels = c(0, 1),
                   labels = c("w", "m"))

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktorielle ANOVA) --> 
G(Ergebnis berichten)

style F fill: #009e73

Zweifaktorielle ANOVA berechnen

Voraussetzungen

  • Skalenniveau
  • Unabhängigkeit der Messungen
  • Varianzhomogenität
  • Normalverteilung

Zweifaktorielle ANOVA berechnen

Voraussetzungen - Varianzhomogenität

Zeig mir den Code
car::leveneTest(likes ~ ani_f * smp_f,
                ds)

Zweifaktorielle ANOVA berechnen

Voraussetzungen - Varianzhomogenität

Levene's Test for Homogeneity of Variance (center = median)
       Df F value Pr(>F)
group   3  1.7991 0.1468
      396               

keine Varianzhomogenität gegeben!

aber bei dieser großen Stichprobe unproplematisch!

Zweifaktorielle ANOVA berechnen

Voraussetzungen - Normalverteilung

Graphisch

Zeig mir den Code
ds |> 
  ggplot(aes(x = likes)) + # x enspricht unserer AV (Likes)
  geom_histogram() +
  facet_grid(ani_f ~ smp_f) + # Brauchen wir damit wir eine 2x2 Matrix bekommmen
  theme_classic()

Zweifaktorielle ANOVA berechnen

Voraussetzungen - Normalverteilung

Graphisch

Voraussetzungen - Normalverteilung

Statistisch

Zeig mir den Code
ds |> 
  filter(ani_f == "Hund" & smp_f == "Instagramm") -> ds_hi
  

ks.test(ds_hi$likes,
          "pnorm",
          mean = mean(ds$likes, na.rm = TRUE),
          sd = sd(ds$likes, na.rm = TRUE))

bei dieser Stichprobengröße wird der Voraussetzungstest “immer” signifikant

Zweifaktorielle ANOVA berechnen

Modell spezifizieren

Zeig mir den Code
# Wir müssen zunächst ein Regressionsobjekt erstellen
mod_anova <- lm(likes ~ ani_f * smp_f, # * steht für Haupteffekte und Interatkion
                data = ds)

## Wir brauchen Typ III Sum of Squares 
mod_III <- car::Anova(mod = mod_anova,
                      type = 3)

Zweifaktorielle ANOVA berechnen

Modell spezifizieren

Anova Table (Type III tests)

Response: likes
             Sum Sq  Df  F value    Pr(>F)    
(Intercept) 1605796   1 13816.41 < 2.2e-16 ***
ani_f         41530   1   357.32 < 2.2e-16 ***
smp_f         45723   1   393.40 < 2.2e-16 ***
ani_f:smp_f   78148   1   672.39 < 2.2e-16 ***
Residuals     46025 396                       
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Zweifaktorielle ANOVA berechnen

Effektröße berechnen

Zeig mir den Code
effectsize::eta_squared(mod_III)

Zweifaktorielle ANOVA berechnen

Effektröße berechnen

# Effect Size for ANOVA (Type III)

Parameter   | Eta2 (partial) |       95% CI
-------------------------------------------
ani_f       |           0.47 | [0.42, 1.00]
smp_f       |           0.50 | [0.44, 1.00]
ani_f:smp_f |           0.63 | [0.59, 1.00]

- One-sided CIs: upper bound fixed at [1.00].

Zweifaktorielle ANOVA berechnen

Berechnen der paarweisen Vergleiche

… werden auch Simple-Effects gennant

Zeig mir den Code
post <- emmeans::emmeans(mod_anova, 
                            ~ ani_f | smp_f)  # Hier müssen wir nach dem | nur die zweite UV einsetzen

pairs(post, adjust = "tukey" )

post_1 <- emmeans::emmeans(mod_anova, 
                            ~  smp_f | ani_f)  # Was passiert, wenn wir die Reihenfolge der UVs ändern?

pairs(post_1, adjust = "tukey" )

Zweifaktorielle ANOVA berechnen

Berechnen der paarweisen Vergleiche

… werden auch Simple-Effects gennant

smp_f = Instagramm:
 contrast     estimate   SE  df t.ratio p.value
 Hund - Katze     28.8 1.52 396  18.903  <.0001

smp_f = TikTok:
 contrast     estimate   SE  df t.ratio p.value
 Hund - Katze    -27.1 1.52 396 -17.768  <.0001



Vertauschen der UVs

ani_f = Hund:
 contrast            estimate   SE  df t.ratio p.value
 Instagramm - TikTok     30.2 1.52 396  19.834  <.0001

ani_f = Katze:
 contrast            estimate   SE  df t.ratio p.value
 Instagramm - TikTok    -25.7 1.52 396 -16.837  <.0001

Zweifaktorielle ANOVA berechnen

Berechnen der paarweisen Vergleiche

Effektstärken

Zeig mir den Code
emmeans::eff_size(post,
                  sigma = sqrt(mod_III$`Sum Sq`[5] / (nrow(ds) - 2)), # Schätzung der Populationsvarianz
                  edf = mod_III$Df[5]) # Wir greifen direkt auf die Ergebnisse des Modells zu

Zweifaktorielle ANOVA berechnen

Berechnen der paarweisen Vergleiche

Effektstärken

smp_f = Instagramm:
 contrast     effect.size    SE  df lower.CL upper.CL
 Hund - Katze        2.68 0.171 396     2.34     3.02

smp_f = TikTok:
 contrast     effect.size    SE  df lower.CL upper.CL
 Hund - Katze       -2.52 0.168 396    -2.85    -2.19

sigma used for effect sizes: 10.75 
Confidence level used: 0.95 

Zweifaktorielle ANOVA berechnen

Berechnen der paarweisen Vergleiche

Recap eff_size()

Was bedeuten die Argumente

  • object = ein emmeans-Objekt, dass wir erstellt haben
  • sigma = Standardabweichung der Fehler
    \(\hat{\sigma} = \sqrt{\frac{SSE}{n-2}}\)
  • edf = Freiheitsgrade der Residuen


Anova Table (Type III tests)

Response: likes
             Sum Sq  Df  F value    Pr(>F)    
(Intercept) 1605796   1 13816.41 < 2.2e-16 ***
ani_f         41530   1   357.32 < 2.2e-16 ***
smp_f         45723   1   393.40 < 2.2e-16 ***
ani_f:smp_f   78148   1   672.39 < 2.2e-16 ***
Residuals     46025 396                       
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Ablauf

flowchart TB

A(Daten einlesen) --> 
B(Übersicht verschaffen) --> 
C(Namen brauchbar machen) --> 
D(Ergeben die Daten Sinn?) --> 
E(Skalenwerte berechnen) --> 
F(zweifaktorielle ANOVA) --> 
G(Ergebnis berichten)

style G fill: #009e73

Ergebnis berichten

Deskriptive Werte

Zeig mir den Code
ds |> 
  group_by(ani_f, smp_f) |> 
  summarise(
    M = round(
      mean(likes, 
           na.rm = TRUE),
      2),
    
    SD = round(
      sd(likes, 
           na.rm = TRUE),
      2)) 

Ergebnis berichten

Deskriptive Werte

ani_f smp_f M SD
Hund Instagramm 126.72 12.08
Hund TikTok 96.48 11.05
Katze Instagramm 97.90 10.78
Katze TikTok 123.57 8.98

Ergebnis berichten

APA-konfrom



“Die ANOVA zeigte einen signifikanten Haupteffekt des Tieres. Hundebilder bekamen mehr Likes als Katzenbilder, F(1, 343) = 357.32, p < .001, η² = 0.47, 95% CI [0.42, 1.00]. Zusätzlich zeigte die ANOVA einen Haupteffekt der Social-Media-Plattform. Die Darstellung auf Instagramm führte zu mehr Likes als auf TikTok, F(1, 343) = 393.40,
p < .001, η² = 0.50, 95% CI [0.44 , 1.00]. Die ANOVA brachte auch einen signifkanten Interaktionseffekt hervor, F(1, 343) = 672.39, p < .001, η² = 0.63, 95% CI [0.59, 1.00].

Einzelvergleiche zeigten, dass Hundebilder auf Instagramm mehr Likes erzielten, t(396) = 18.90, p < .001, d = 2.68, 95% CI [2.34, 3.02]. Auf TikTok erzielten Katzenbilder mehr Likes, t(396) = 18.90, p < .001, d = -2.52, 95% CI [-2.85, -2.19].

Ergebnis berichten

Balkendiagram

Zeig mir den Code
# Welche Farbe hätte ich denn gerne``
mf <- c("#00AFBB", "#E7B800")

# Erstellen des Plots
ds |> 
  ggplot(aes(x = ani_f,
             y = likes,
             fill = smp_f,
             grou = smp_f)) +
  stat_summary(geom = "errorbar",
               position = position_dodge(.9),
               width = 0.3) +
  stat_summary(geom = "bar",
               position = "dodge") + 
  scale_fill_manual("Social-Media-Plattform", 
                    values = mf) +
  scale_y_continuous(n.breaks = 11) +
  labs(x = "",
       y = "Likes") +
  theme_classic(base_size = 18)

Ergebnis berichten

Balkendiagram

Übung




  • Durchlaufen Sie sämtliche Schritte mit dem Alter mit Gender und Tier als UVs!
  • Erstellen Sie ein Liniendiagramm mit 95% CI